home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / icmp.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  5KB  |  201 lines

  1. /* Internet Control Message Protocol */
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "internet.h"
  5. #include "timer.h"
  6. #include "iface.h"
  7. #include "ip.h"
  8. #include "icmp.h"
  9.  
  10. struct icmp_errors icmp_errors;
  11. struct icmp_stats icmp_stats;
  12.  
  13. /* Process an incoming ICMP packet */
  14. /*ARGSUSED*/
  15. void
  16. icmp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  17. struct mbuf *bp;    /* Pointer to ICMP message */
  18. char protocol;        /* Should always be ICMP_PTCL */
  19. int32 source;        /* Sender of ICMP message */
  20. int32 dest;        /* Us */
  21. char tos;        /* Type of Service */
  22. int16 length;        /* Length of ICMP message */
  23. char rxbroadcast;
  24. {
  25.     struct mbuf *htonicmp(),*tbp;
  26.     struct icmp icmp;    /* ICMP header */
  27.     struct ip ip;        /* Offending datagram header */
  28.     int16 type;        /* Type of ICMP message */
  29.  
  30.     if(rxbroadcast){
  31.         /* Broadcast ICMP packets are to be IGNORED !! */
  32.         icmp_errors.bdcsts++;
  33.         free_p(bp);
  34.         return;
  35.     }
  36.     if(cksum(NULLHEADER,bp,length) != 0){
  37.         /* Bad ICMP checksum; discard */
  38.         icmp_errors.checksum++;
  39.         free_p(bp);
  40.         return;
  41.     }
  42.     ntohicmp(&icmp,&bp);
  43.  
  44.     /* Process the message. Some messages are passed up to the protocol
  45.      * module for handling, others are handled here.
  46.      */
  47.     type = icmp.type;
  48.     if(type < ICMP_TYPES)
  49.         icmp_stats.input[type]++;
  50.  
  51.     switch(uchar(type)){
  52.     case TIME_EXCEED:    /* Time-to-live Exceeded */
  53.     case DEST_UNREACH:    /* Destination Unreachable */
  54.     case QUENCH:        /* Source Quench */
  55.         ntohip(&ip,&bp);    /* Extract offending IP header */
  56.         switch(uchar(ip.protocol)){
  57.         case TCP_PTCL:
  58.             tcp_icmp(ip.source,ip.dest,icmp.type,icmp.code,&bp);
  59.             break;
  60.         }
  61.         break;
  62.     case ECHO:        /* Echo Request */
  63.         /* Change type to ECHO_REPLY, recompute checksum,
  64.          * and return datagram.
  65.          */
  66.         icmp.type = ECHO_REPLY;
  67.         if((tbp = htonicmp(&icmp,bp)) == NULLBUF){
  68.             free_p(bp);
  69.             return;
  70.         }
  71.         icmp_stats.output[ECHO_REPLY]++;
  72.         ip_send(dest,source,ICMP_PTCL,tos,0,tbp,length,0,0);
  73.         return;
  74.     case REDIRECT:        /* Redirect */
  75.     case PARAM_PROB:    /* Parameter Problem */
  76.         break;
  77.        case ECHO_REPLY:        /* Echo Reply */
  78.         echo_proc(source,dest,&icmp);
  79.         break;
  80.     case TIMESTAMP:        /* Timestamp */
  81.     case TIME_REPLY:    /* Timestamp Reply */
  82.     case INFO_RQST:        /* Information Request */
  83.     case INFO_REPLY:    /* Information Reply */
  84.         break;
  85.     }
  86.     free_p(bp);
  87. }
  88. /* Return an ICMP response to the sender of a datagram.
  89.  * Unlike most routines, the callER frees the mbuf.
  90.  */
  91. int
  92. icmp_output(ip,data,type,code,args)
  93. struct ip *ip;        /* Header of offending datagram */
  94. struct mbuf *data;    /* Data portion of datagram */
  95. char type,code;        /* Codes to send */
  96. union icmp_args *args;
  97. {
  98.     struct mbuf *htonicmp();
  99.     struct mbuf *htonip();
  100.     struct mbuf *bp;
  101.     struct icmp icmp;    /* ICMP protocol header */
  102.     int16 dlen;        /* Length of data portion of offending pkt */
  103.     int16 length;        /* Total length of reply */
  104.     extern int32 ip_addr;    /* Our IP address */
  105.  
  106.     if(ip == NULLIP)
  107.         return -1;
  108.     if(type < ICMP_TYPES)
  109.         icmp_stats.output[type]++;
  110.  
  111.     if(uchar(ip->protocol) == ICMP_PTCL){
  112.         /* Never send an ICMP message about another ICMP message */
  113.         icmp_errors.noloop++;
  114.         return -1;
  115.     }
  116.     /* Compute amount of original datagram to return.
  117.      * We return the original IP header, and up to 8 bytes past that.
  118.      */
  119.     dlen = min(8,len_mbuf(data));
  120.     length = dlen + ICMPLEN + IPLEN + ip->optlen;
  121.     /* Take excerpt from data portion */
  122.     if(data != NULLBUF && (bp = copy_p(data,dlen)) == NULLBUF)
  123.         return -1;    /* The caller will free data */
  124.  
  125.     /* Recreate and tack on offending IP header */
  126.     if((data = htonip(ip,bp)) == NULLBUF){
  127.         free_p(bp);
  128.         return -1;
  129.     }
  130.     icmp.type = type;
  131.     icmp.code = code;
  132.     switch(uchar(icmp.type)){
  133.     case PARAM_PROB:
  134.         icmp.args.pointer = args->pointer;
  135.         break;
  136.     case REDIRECT:
  137.         icmp.args.address = args->address;
  138.         break;
  139.     case ECHO:
  140.     case ECHO_REPLY:
  141.     case INFO_RQST:
  142.     case INFO_REPLY:
  143.     case TIMESTAMP:
  144.     case TIME_REPLY:
  145.         icmp.args.echo.id = args->echo.id;
  146.         icmp.args.echo.seq = args->echo.seq;
  147.         break;
  148.     default:
  149.         icmp.args.unused = 0;
  150.         break;
  151.     }
  152.     /* Now stick on the ICMP header */
  153.     if((bp = htonicmp(&icmp,data)) == NULLBUF){
  154.         free_p(data);
  155.         return -1;
  156.     }
  157.     return ip_send(ip_addr,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
  158. }
  159. /* Generate ICMP header in network byte order, link data, compute checksum */
  160. struct mbuf *
  161. htonicmp(icmp,data)
  162. struct icmp *icmp;
  163. struct mbuf *data;
  164. {
  165.     struct mbuf *bp;
  166.     register char *cp;
  167.     int16 checksum;
  168.  
  169.     if((bp = pushdown(data,ICMPLEN)) == NULLBUF)
  170.         return NULLBUF;
  171.     cp = bp->data;
  172.  
  173.     *cp++ = icmp->type;
  174.     *cp++ = icmp->code;
  175.     cp = put16(cp,0);        /* Clear checksum */
  176.     cp = put16(cp,icmp->args.echo.id);
  177.     cp = put16(cp,icmp->args.echo.seq);
  178.  
  179.     /* Compute checksum, and stash result */
  180.     checksum = cksum(NULLHEADER,bp,len_mbuf(bp));
  181.     cp = &bp->data[2];
  182.     cp = put16(cp,checksum);
  183.  
  184.     return bp;
  185. }
  186. /* Pull off ICMP header */
  187. int
  188. ntohicmp(icmp,bpp)
  189. struct icmp *icmp;
  190. struct mbuf **bpp;
  191. {
  192.     if(icmp == (struct icmp *)NULL)
  193.         return -1;
  194.     icmp->type = pullchar(bpp);
  195.     icmp->code = pullchar(bpp);
  196.     (void) pull16(bpp);        /* Toss checksum */
  197.     icmp->args.echo.id = pull16(bpp);
  198.     icmp->args.echo.seq = pull16(bpp);
  199.     return 0;
  200. }
  201.